
package org.crepi22.finecrop;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * @author pierre
 * Handle argument parsing and selection of files.
 */
public class Main {
    
    PhotoView photoView;
    JFrame frame;
    private Controller controller;
    private FCAction mode;

    Main(FCAction mode) throws IOException {
        this.mode = mode;
        createAndShowGUI();
    }

    /**
     * Process a list of files.
     * @param todo
     */
    public void run(List<File> todo) {
        if (todo.size() > 0) controller.perform(todo, mode);
        else frame.dispose();
    }

    private void createAndShowGUI() throws IOException {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) { //$NON-NLS-1$
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            JFrame.setDefaultLookAndFeelDecorated(true);
        }
        frame = new JFrame(OS.APP_NAME);

        OS.decorate(frame,OS.APP_NAME);
        JPanel panel = new JPanel();
        BorderLayout layout = new BorderLayout();
        panel.setLayout(layout);
        JPanel topLine = new JPanel();
        JToolBar toolbar = new JToolBar(Messages.getString("Main.Toolbar_Title"), JToolBar.VERTICAL); //$NON-NLS-1$
        topLine.setBackground(Color.LIGHT_GRAY);
        topLine.setLayout(new BoxLayout(topLine, BoxLayout.X_AXIS));
        
        frame.setPreferredSize(new Dimension(600, 600));
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setContentPane(panel);

        // Create and set up the content pane.
        List<String> states = new ArrayList<String>();
        List<String> tooltips = new ArrayList<String>();
        FCAction cursor = mode;
        while(cursor != null) {
            int i = cursor.kind - 1;
            states.add(Controller.STATES[i]);
            tooltips.add(Controller.TOOLTIPS[i]);
            cursor = cursor.continuation;
        }
        final StateLine stateLine = new StateLine(states, tooltips);
        photoView = new PhotoView(frame);
        controller = new Controller(frame, photoView, stateLine, toolbar);
        photoView.setOpaque(true);
        topLine.add(stateLine);
        stateLine.setBorder(BorderFactory.createEmptyBorder(1, 5, 1, 5)); 
        panel.add(topLine, BorderLayout.PAGE_START);
        panel.add(toolbar,BorderLayout.LINE_END);
        panel.add(photoView, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    /**
     * Entry point
     * 
     * @param args
     */
    public static void main(String args[]) {
        List<String> fileEntries = new ArrayList<String>();
        FCAction mode = FCAction.PHOTO_MODE; // Default mode.
        int l = args.length;
        for(int i=0; i < l; i++) {
            String arg = args[i];
            if(arg != null && arg.length() > 0 && arg.charAt(0) == '-') {
                if(arg.equals("-p")) { //$NON-NLS-1$
                    mode = FCAction.PHOTO_MODE;
                } else if(arg.equals("-b")) { //$NON-NLS-1$
                    mode =  FCAction.BOOK_MODE;
                } else if(arg.equals("-c")) { //$NON-NLS-1$
                    if (++i >= l) break;
                    mode = scanMode(args[i]);
                } else if(arg.equals("-h")) { //$NON-NLS-1$
                    showHelp();
                } else {
                    error(Messages.getString("Main.Error_option")); //$NON-NLS-1$
                }
            } else {
                fileEntries.add(arg);
            }
        }
        final FCAction theMode = mode;
        final List<File> files = getArguments(fileEntries);
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Main main;
                try {
                    main = new Main(theMode);
                    main.run(files);
                } catch (IOException e) {
                }
            }
        });
    }

    private static void showHelp() {
        System.err.println(OS.APP_NAME + Messages.getString("Main.help_arguments")); //$NON-NLS-1$
        System.err.println(Messages.getString("Main.b_arg_help") + //$NON-NLS-1$
                Messages.getString("Main.p_arg_help") + //$NON-NLS-1$
                Messages.getString("Main.c_arg_help") + //$NON-NLS-1$
                Messages.getString("Main.h_arg_help")); //$NON-NLS-1$
        System.exit(0);
    }

    private static FCAction scanMode(String spec) {
        int l = spec.length();
        FCAction result = new FCAction(FCAction.CONFIRM, null);
        for(int i = l-1; i >=0; i--) {
            switch(spec.charAt(i)) {
                case 'R':
                    result = new FCAction(FCAction.ROTATE, result);
                    break;
                case 'C':
                    result = new FCAction(FCAction.CROP, result);
                    break;
                case 'M':
                    result = new FCAction(FCAction.MULTICROP, result);
                    break;
                default:
                    error(String.format(Messages.getString("Main.error_action"), spec.charAt(i))); //$NON-NLS-1$
            }
        }
        return result;
    }

    private static void error(String msg) {
        System.err.println(msg);
        System.exit(1);
    }

    private static List<File> getArguments(List<String> args) {
        final String[] suffixes = ImageIO.getReaderFileSuffixes();
        
        FileFilter filter = new FileFilter() {
            @Override
            public boolean accept(File arg) {
                String filename = arg.getName();
                String extension = filename.substring(filename.lastIndexOf(".") + 1, //$NON-NLS-1$
                        filename.length());
                for (String suffix : suffixes) {
                    if (suffix.equalsIgnoreCase(extension))
                        return true;
                }
                return false;
            }
        };

        List<File> result = new ArrayList<File>();
        if (args.size() == 0) {
            @SuppressWarnings("serial")
            JFileChooser chooser = new JFileChooser() {
                @Override
                protected JDialog createDialog(Component parent) throws HeadlessException {
                    JDialog dialog = super.createDialog(parent);
                    try { OS.decorate(dialog, null); } catch (IOException e) {}
                    return dialog;
                }
            };
            chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
            chooser.setFileFilter(new FileNameExtensionFilter(Messages.getString("Main.image_filter_name"), suffixes)); //$NON-NLS-1$
            int retVal = chooser.showOpenDialog(null);
            if (retVal == JFileChooser.APPROVE_OPTION) {
                args.add(chooser.getSelectedFile().getAbsolutePath());
            }
        } 
        for (String name : args) {
            File entry = new File(name);
            if (entry == null || !entry.exists())
                continue;
            if (entry.isDirectory()) {
                File[] entries = entry.listFiles(filter);
                result.addAll(Arrays.asList(entries));
            } else {
                result.add(entry);
            }
        }
        return result;
    }

}
